package cn.code.auth.authorize.security.url;

import cn.code.admin.security.MyGrantedAuthority;
import cn.code.admin.security.UrlNeedPower;
import cn.code.admin.model.AuthTbRolePower;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
import java.util.Iterator;


/**
 * Created by yangyibo on 17/1/19.
 */
@Service
public class UrlAccessDecisionManager implements AccessDecisionManager {
    @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
        HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
        String url, method;
        if ("anonymousUser".equals(authentication.getPrincipal())
                || matchers("/images/**", request)
                || matchers("/js/**", request)
                || matchers("/css/**", request)
                || matchers("/fonts/**", request)
                || matchers("/", request)
                || matchers("/index.html", request)
                || matchers("/favicon.ico", request)
                || matchers("/login", request)) {
            return;
        } else {
//            for (GrantedAuthority ga : authentication.getAuthorities()) {
//                if (ga instanceof UrlGrantedAuthority) {
//                    UrlGrantedAuthority urlGrantedAuthority = (UrlGrantedAuthority) ga;
//                    url = urlGrantedAuthority.getPermissionUrl();
//                    method = urlGrantedAuthority.getMethod();
//                    if (matchers(url, request)) {
//                        if (method.equals(request.getMethod()) || "ALL".equals(method)) {
//                            return;
//                        }
//                    }
//                }
    //        }
            ConfigAttribute c;
            String needRole="";
            for(Iterator<ConfigAttribute> iter = configAttributes.iterator(); iter.hasNext(); ) {
                c = iter.next();
                if( c instanceof UrlNeedPower){
                    UrlNeedPower urlNeedPower=(UrlNeedPower)c;
                    for(GrantedAuthority ga : authentication.getAuthorities()) {//authentication 为在注释1 中循环添加到 GrantedAuthority 对象中的权限信息集合
                        if(urlNeedPower.getRole()==null){
                            return;
                        }
                        if(ga instanceof MyGrantedAuthority){
                            MyGrantedAuthority myGrantedAuthority=(MyGrantedAuthority)ga;
                            if(urlNeedPower.getRole().trim().equals(myGrantedAuthority.getRoleName())){
                                System.out.println("need-role::"+urlNeedPower.getRole()+" have-role:"+myGrantedAuthority.getRoleName());
                                if(myGrantedAuthority.getPowers()==null||myGrantedAuthority.getPowers().size()<1){
                                    return ;
                                }
                                if(urlNeedPower.getPermissions()==null||urlNeedPower.getPermissions().isEmpty()){
                                    return ;
                                }
                                for (AuthTbRolePower power: myGrantedAuthority.getPowers()) {
                                    //System.out.println("need-power::"+urlNeedPower.getPermissions()+" have-power:"+power.getName());
                                    if(urlNeedPower.getPermissions().trim().equals(power.getName())){
                                        return ;
                                    }
                                }
                            }
                        }
                    }
                }

            }
        }
        throw new AccessDeniedException("no right");
    }


    @Override
    public boolean supports(ConfigAttribute attribute) {
        return true;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }


    private boolean matchers(String url, HttpServletRequest request) {
        AntPathRequestMatcher matcher = new AntPathRequestMatcher(url);
        if (matcher.matches(request)) {
            return true;
        }
        return false;
    }
}
